import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Clasa Logger reprezinta un nod de jurnalizare responsabil sa ofere
 * posiblitatea jurnalizarii activitatii clientilor de catre nodul logic
 * utilizand mecanismul RMI.
 * 
 */
public class Logger extends UnicastRemoteObject implements RILogger {

	/**
	 * Default serial version.
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Constante cu tipurile de actiuni ce se pot jurnaliza in fisierul de log.
	 */
	public static final String L_STUD = "[lista studenti]";
	public static final String L_CURS = "[lista cursuri]";
	public static final String L_STUD_INREG_UN_CURS = "[lista studenti inregistrati la un curs]";
	public static final String L_CURS_INREG_UN_STUD = "[lista cursurilor la care e inregistrat un student]";
	public static final String L_CURS_ABS = "[lista cursurilor absolvite de un student]";
	public static final String INREG_STUD_CURS = "[inregistrare student la un curs]";
	public static final String IESIRE = "[iesire]";

	private static final String LOGGER_NAME = "Logger";

	/**
	 * Referinta catre BufferedWriter catre fisierul de jurnal de pe disk.
	 */
	private BufferedWriter out;

	/**
	 * Referita catre modul de formatare a timpului in fisierul de jurnal de pe
	 * disk.
	 */
	private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	/**
	 * Construieste nodul de jurnalizarea care ofera posibilitatea logarii
	 * actiunilor clientilor.
	 * 
	 * @param sLogFileName
	 *            numele fisierul de pe disk unde se va face jurnalizarea
	 *            actiunilor clientilor.
	 * @throws RemoteException
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public Logger(String sLogFileName) throws RemoteException, FileNotFoundException, IOException {
		try {

			// Initilizarea referintei BufferedWriter.
			out = new BufferedWriter(new FileWriter(sLogFileName, true));
		} catch (IOException e) {
			// Daca apare IOException atunci se afiseaza exceptia iar nodul
			// Logger se inchide.
			System.err.println("IOException in nodul Logger. Conexiunea catre fisierul de log '" + sLogFileName + "' nu a putut fi realizata.");
			System.err.println("Nodul Logger se opreste.");
			System.exit(1);
		}
	}

	/**
	 * Elibereaza resursa deschisa de tipul BufferedWriter.
	 */
	protected void eliberareResurse() {
		try {
			out.close();
		} catch (IOException e) {
			System.err.println("IOException la eliberarea resurselor.");
		}
	}

	/**
	 * Logarea actinilor.
	 * 
	 * @param identificatorClient
	 *            identificatorul clientului
	 * @param tipComanda
	 *            tipul comnezii
	 * @return
	 * @throws RemoteException
	 */
	public String log(String identificatorClient, String tipComanda) throws RemoteException {
		try {

			// Scrierea actiunii sub forma "[id client] [timp] [tip actiunie]"
			// in fisierul de jurnal.
			out.write(identificatorClient + "\t" + format.format(new Date()) + "\t" + tipComanda + System.getProperty("line.separator"));
			out.flush();
		} catch (IOException e) {
			System.err.println("Nodul Logger nu a putut efectua jurnalizarea.");
		}
		return null;
	}

	/**
	 * Creare si lansare nod de jurnalizare.
	 * 
	 * E asteptat un parametru: numele fisierul de jurnalizare de pe disk.
	 * 
	 * @param args
	 *            numele fisierul de jurnalizare de pe disk unde se vor loga
	 *            actiunile clientilor.
	 */
	public static void main(String args[]) {
		// Verificarea numarului de parametri.
		if (args.length != 1) {
			System.err.println("Numar incorect de parametrii");
			System.err.println("Utilizare: java Logger <fisier de log>");
			System.exit(1);
		}

		try {
			// Creare nod de jurnalizare pentru comunicare prin RMI.
			Logger objLogger = new Logger(args[0]);
			Naming.bind(LOGGER_NAME, objLogger);
			System.out.println("Nodul Logger este gata pentru servire.");

			// Asteptare intrerupere de la utilizator.
			System.out.println("Apasati Enter pentru terminare.");
			System.in.read();

			// Eliberare resurse si terminare.
			Naming.unbind(LOGGER_NAME);
			objLogger.eliberareResurse();
			System.out.println("Nodul Logger se dezactiveaza. Apasati Ctrl-C daca dureaza prea mult.");
		} catch (java.rmi.ConnectException e) {
			// Afisare mesaj de eroare si exit.
			System.err.println("Java RMI error: verificat daca rmiregistry este pornit.");
			System.exit(1);
		} catch (Exception e) {
			// Afisare informatii pentru depanare.
			System.err.println("Unexpected exception at " + LOGGER_NAME);
			e.printStackTrace();
			System.exit(1);
		}
	}

}